home *** CD-ROM | disk | FTP | other *** search
/ CU Amiga Super CD-ROM 17 / CU Amiga Magazine's Super CD-ROM 17 (1997)(EMAP Images)(GB)[!][issue 1997-12].iso / CUCD / Programming / DiceSource / src / dc1 / cexp.c < prev    next >
C/C++ Source or Header  |  1997-09-09  |  22KB  |  892 lines

  1. /*
  2.  *    (c)Copyright 1992-1997 Obvious Implementations Corp.  Redistribution and
  3.  *    use is allowed under the terms of the DICE-LICENSE FILE,
  4.  *    DICE-LICENSE.TXT.
  5.  */
  6.  
  7. /*
  8.  *  CEXP.C
  9.  *
  10.  *  Expression Parser.    These routines generate an expression tree.
  11.  *
  12.  *  unary: ! ~ & * ++ -- [exp] (..,..)
  13.  *
  14.  *  binary: % %= & && &= * *= + += , - -= -> . / /= << <<= =
  15.  *        >> >>= ^ ^= | || |=
  16.  *                            precedence
  17.  *  boolean:    < <= == >= > !=
  18.  *                         postf: () [] -> .
  19.  *  special:    exp ? exp : exp          unary: ! ~ ++ -- - * & sizeof
  20.  *                         bin:   * / %
  21.  *  terminator: (exp)                    + -
  22.  *        varid                    << >>
  23.  *        tokid (procedure call?)         < <= > >=
  24.  *        constant                == !=
  25.  *                            &
  26.  *                            ^
  27.  *                            |
  28.  *                            &&
  29.  *                            ||
  30.  *                            ?:
  31.  *                            = += -= *= /= %= |= &= ^= >>= <<=
  32.  *                            ,
  33.  */
  34.  
  35. /*
  36. **      $Filename: cexp.c $
  37. **      $Author: dice $
  38. **      $Revision: 30.325 $
  39. **      $Date: 1995/12/24 05:38:04 $
  40. **      $Log: cexp.c,v $
  41.  * Revision 30.325  1995/12/24  05:38:04  dice
  42.  * .
  43.  *
  44.  * Revision 30.156  1995/01/11  05:04:40  dice
  45.  * .
  46.  *
  47.  * Revision 30.5  1994/06/13  18:37:24  dice
  48.  * .
  49.  *
  50.  * Revision 30.0  1994/06/10  18:04:47  dice
  51.  * .
  52.  *
  53.  * Revision 1.8  1994/04/15  20:41:18  jtoebes
  54.  * Handle trailing commas more properly.
  55.  *
  56.  * Revision 1.7  1994/01/03  13:21:01  jtoebes
  57.  * Fixed BUG10002 - Enforcer hit in DC1.
  58.  * Changed the default for a symbol to be a long instead of a function type.
  59.  *
  60.  * Revision 1.6  1993/11/22  00:28:36  jtoebes
  61.  * Final cleanup to eliminate all cerror() messages with strings.
  62.  *
  63.  * Revision 1.5  1993/10/16  14:59:48  jtoebes
  64.  * Allowed optional comma after last element in an array initialization.
  65.  *
  66.  * Revision 1.4  1993/09/11  23:24:17  jtoebes
  67.  * Fixed BUG00047 - DC1 failes to warn about missing , in initialized expression.
  68.  * Changed logic for comma search to be more rigerous.  All old code should
  69.  * continue to compile.
  70.  *
  71.  * Revision 1.3  1993/09/05  23:56:22  jtoebes
  72.  * Fixed BUG06045 - Enforcer hit for invalid structure definitions.
  73.  * Added code to skip over current level of nesting when too many
  74.  * initializers are given for a structure.
  75.  * Created match_nesting subroutine for general usage to do this.
  76.  *
  77. **/
  78.  
  79. #include "defs.h"
  80.  
  81. #define LR    1        /*    left to right, else        */
  82. #define RL    2        /*    right to left            */
  83. #define QBIN    4        /*    binary operator, else unary */
  84. #define BLR    (LR|QBIN)
  85. #define BRL    (RL|QBIN)
  86.  
  87. #define XX    0    /*  don't care (situation never comes up)   */
  88.  
  89. /*static short ExpPrec[64] = EXPPREC;*/
  90.  
  91. Prototype short CompExp(short, Exp **, long);
  92. Prototype short CompBracedAssign(short, Type *, Exp **, short, Symbol *);
  93. Prototype short match_nesting(short);
  94.  
  95. Local void PushOp(Exp **, Exp **, void (*)(Exp **), long, long);
  96. Local void PushAtom(Exp **, Exp **, void (*)(Exp **));
  97. Local void CombineOp(Exp **, Exp **);
  98.  
  99. Exp *HackTmpExp;        /*  free expression cache   */
  100.  
  101. short
  102. CompExp(short t, Exp **pexp, long commaok)
  103. {
  104.     short unary = 1;        /*  operator state  */
  105.     short notdone = 1;
  106.     short parens = 0;
  107.     short quests = 0;        /*  # of question marks for colons */
  108.     Exp   *opStack = NULL;    /*  operator stack  */
  109.     Exp   *atomStack = NULL;    /*  atom stack        */
  110.  
  111.  
  112.     if (t == TokSemi)
  113.     zerror(EFATAL_EXPECTED_EXP);
  114.  
  115.     *pexp = NULL;
  116.  
  117.     for (;;) {
  118.     if (unary) {        /*    construct quantity  */
  119.         switch(t) {
  120.         case TokNot:    /*  !exp    */
  121.         PushOp(&atomStack, &opStack, GenNot, 140, RL);
  122.         break;
  123.         case TokAnd:    /*  &exp    */
  124.         PushOp(&atomStack, &opStack, GenAddr, 140, RL);
  125.         opStack->ex_Token = TokAddr;
  126.         break;
  127.         case TokStar:    /*  *exp    */
  128.         PushOp(&atomStack, &opStack, GenInd, 140, RL);
  129.         break;
  130.         case TokPlPl:    /*  ++exp   */
  131.         PushOp(&atomStack, &opStack, GenPreInc, 140, RL);
  132.         opStack->ex_Token = TokPreInc;
  133.         break;
  134.         case TokMiMi:    /*  --exp   */
  135.         PushOp(&atomStack, &opStack, GenPreDec, 140, RL);
  136.         opStack->ex_Token = TokPreDec;
  137.         break;
  138.         case TokPl:     /*  +exp    */
  139.         break;
  140.         case TokMi:     /*  -exp    */
  141.         PushOp(&atomStack, &opStack, GenNeg, 140, RL);
  142.         break;
  143.         case TokTilde:    /*  ~exp    */
  144.         PushOp(&atomStack, &opStack, GenCompl, 140, RL);
  145.         break;
  146.         case TokSizeof:    /*  sizeof exp    */
  147.         t = GetToken();
  148.         if (t == TokLParen) {    /*  check sizeof(type)    */
  149.             Type *baseType;
  150.             Type *type;
  151.             Symbol *sym;
  152.             long  baseFlags;
  153.             long  regFlags;
  154.  
  155.             t = GetToken();
  156.  
  157.             switch(t) {
  158.             case TokStruct:
  159.             case TokEnum:
  160.             case TokUnion:
  161.             case TokTypeQual:
  162.             case TokRegQual:
  163.             case TokTypeId:
  164.             case TokTypeof:
  165.             t = CompType(t, &baseType, &baseFlags, ®Flags);
  166.             type = baseType;
  167.             t = CompTypeDeclarators(t, &type, &sym, baseFlags);
  168.             if (t != TokRParen)
  169.                 zerror(EFATAL_SYNTAX_ERROR_EXP);
  170.             t = GetToken();
  171.             PushAtom(&atomStack, &opStack, GenSizeof);
  172.             atomStack->ex_Type = type;
  173.             unary = 0;
  174.             continue;
  175.             default:
  176.             PushOp(&atomStack, &opStack, GenSizeof, 140, RL);
  177.             ++parens;
  178.             PushOp(&atomStack, &opStack, GenParen, 0, XX);
  179.             opStack->ex_Token = TokLParen;
  180.             continue;   /*    already have next token after paren */
  181.             }
  182.         }
  183.         PushOp(&atomStack, &opStack, GenSizeof, 140, RL);
  184.         continue;    /*  already have next token */
  185.  
  186.         case TokLParen:    /*  (exp)  or (type) or ()  */
  187.         {
  188.             Type *baseType;
  189.             Type *type;
  190.             Symbol *sym;
  191.             long  baseFlags;
  192.             long  regFlags;
  193.  
  194.             t = GetToken();
  195.  
  196.             switch(t) {     /*  (typecast)    */
  197.             case TokStruct:
  198.             case TokEnum:
  199.             case TokUnion:
  200.             case TokTypeQual:
  201.             case TokRegQual:
  202.             case TokTypeId:
  203.             case TokTypeof:
  204.             t = CompType(t, &baseType, &baseFlags, ®Flags);
  205.             type = baseType;
  206.             t = CompTypeDeclarators(t, &type, &sym, baseFlags);
  207.             if (t != TokRParen)
  208.                 zerror(EFATAL_SYNTAX_ERROR_EXP);
  209.             t = GetToken();
  210.             PushOp(&atomStack, &opStack, GenCast, 140, RL);
  211.             opStack->ex_Type = type;
  212.             opStack->ex_Token = TokCast;
  213.             continue;
  214.             case TokRParen:
  215.             PushAtom(&atomStack, &opStack, GenParen);
  216.             unary = 0;
  217.             t = GetToken();
  218.             continue;
  219.             default:        /*  (exp)   */
  220.             ++parens;
  221.             PushOp(&atomStack, &opStack, GenParen, 0, XX);
  222.             opStack->ex_Token = TokLParen;
  223.             continue;   /*    already have next symbol  */
  224.             }
  225.         }
  226.         /* not reached */
  227.         Assert(0);
  228.                 /*  terminator    */
  229.         case TokEnumConst:
  230.         LexIntConst = (long)LexData;
  231.         LexUnsigned = 0;
  232.         case TokIntConst:
  233.         PushAtom(&atomStack, &opStack, GenIntConst);
  234.         atomStack->ex_Stor.st_IntConst = LexIntConst;
  235.         atomStack->ex_Token = t;
  236.         if (LexUnsigned)
  237.             atomStack->ex_Stor.st_Flags |= SF_UNSIGNED;
  238.         unary = 0;
  239.         break;
  240.         case TokStrConst:
  241.         PushAtom(&atomStack, &opStack, GenStrConst);
  242.         atomStack->ex_StrConst = LexStrConst;
  243.         atomStack->ex_StrLen   = LexStrLen;
  244.         atomStack->ex_Token = t;
  245.         unary = 0;
  246.         break;
  247.         case TokFltConst:
  248.         PushAtom(&atomStack, &opStack, GenFltConst);
  249.         atomStack->ex_Stor.st_FltConst = LexStrConst;
  250.         atomStack->ex_Stor.st_FltLen   = LexStrLen;
  251.         atomStack->ex_Token = t;
  252.         atomStack->ex_Type  = LexData;
  253.         unary = 0;
  254.         break;
  255.         case TokVarId:
  256.         /*
  257.          *  If this is a global or external variable, NOT a procedure,
  258.          *  and not already dummied, then add a dummy semantic entry
  259.          *  and var structure to the highest block in the procedure.
  260.          *
  261.          *  we can't put it in lower blocks due to the possibility
  262.          *  of goto past the lea in case it's lea is stuck into a
  263.          *  register.
  264.          */
  265.         {
  266.             Var *var = (Var *)LexData;
  267.  
  268.             PushAtom(&atomStack, &opStack, GenVarRef);
  269.             atomStack->ex_Token = TokVarRef;
  270.             atomStack->ex_Symbol = LexSym;
  271.             atomStack->ex_Var  = var;
  272.             atomStack->ex_Var->Refs += BlockCost + 1;
  273.             unary = 0;
  274.         }
  275.         break;
  276.         case TokId:     /*  possible subroutine?    */
  277.         t = GetToken();
  278.         {
  279.             Var *var = AllocStructure(Var);
  280.  
  281.             if (t != TokLParen)
  282.             {
  283.             zerror(EERROR_UNDEFINED_SYMBOL, SymToString(LexSym));
  284.             /* default is a long */
  285.             var->Type = &LongType;
  286.             }
  287.             else
  288.             {
  289.             /* They used it as a procedure */
  290.             /*
  291.              *  create a variable as a reference to the procedure
  292.              *  specified returning an int.
  293.              */
  294.             var->Type = &DefaultProcType;
  295.             }
  296.  
  297.  
  298.             var->Sym  = LexSym;
  299.             var->Flags = TF_EXTERN;
  300.             var->LexIdx= LFBase->lf_Index;  /* XXX */
  301.  
  302.             BlockAddTop(var);
  303.             SemanticAddTop(LexSym, TokVarId, var); /* XXX */
  304.  
  305.             PushAtom(&atomStack, &opStack, GenVarRef);
  306.             atomStack->ex_Token = TokVarRef;
  307.             atomStack->ex_Symbol= LexSym;
  308.             atomStack->ex_Var    = var;
  309.             ++atomStack->ex_Var->Refs;
  310.         }
  311.         unary = 0;
  312.         continue;    /*  have token */
  313.         default:
  314.         notdone = 0;
  315.         break;
  316.         }
  317.     } else {
  318.         unary = 1;
  319.  
  320.         switch(t) {
  321.         case TokNotEq:    /*  boolean    */
  322.         case TokEqEq:
  323.         PushOp(&atomStack, &opStack, GenBoolCompareSame, 90, BLR);
  324.         opStack->ex_Token = t;
  325.         break;
  326.         case TokLt:
  327.         case TokLtEq:
  328.         case TokGtEq:
  329.         case TokGt:
  330.         PushOp(&atomStack, &opStack, GenBoolCompare, 100, BLR);
  331.         opStack->ex_Token = t;
  332.         break;
  333.         case TokPercentEq:
  334.         PushOp(&atomStack, &opStack, GenPercentEq, 20, BRL);
  335.         break;
  336.         case TokAndEq:
  337.         PushOp(&atomStack, &opStack, GenAndEq, 20, BRL);
  338.         break;
  339.         case TokStarEq:
  340.         PushOp(&atomStack, &opStack, GenStarEq, 20, BRL);
  341.         break;
  342.         case TokMiEq:
  343.         PushOp(&atomStack, &opStack, GenMiEq, 20, BRL);
  344.         break;
  345.         case TokDivEq:
  346.         PushOp(&atomStack, &opStack, GenDivEq, 20, BRL);
  347.         break;
  348.         case TokLtLtEq:
  349.         PushOp(&atomStack, &opStack, GenLtLtEq, 20, BRL);
  350.         break;
  351.         case TokGtGtEq:
  352.         PushOp(&atomStack, &opStack, GenGtGtEq, 20, BRL);
  353.         break;
  354.         case TokPlEq:
  355.         PushOp(&atomStack, &opStack, GenPlEq, 20, BRL);
  356.         break;
  357.         case TokEq:
  358.         PushOp(&atomStack, &opStack, GenEq, 20, BRL);
  359.         break;
  360.         case TokOrEq:
  361.         PushOp(&atomStack, &opStack, GenOrEq, 20, BRL);
  362.         break;
  363.         case TokCaratEq:
  364.         PushOp(&atomStack, &opStack, GenCaratEq, 20, BRL);
  365.         break;
  366.  
  367.         case TokAndAnd:
  368.         PushOp(&atomStack, &opStack, GenAndAnd, 50, BLR);
  369.         break;
  370.         case TokOrOr:
  371.         PushOp(&atomStack, &opStack, GenOrOr, 40, BLR);
  372.         break;
  373.  
  374.         case TokDiv:
  375.         PushOp(&atomStack, &opStack, GenDiv, 130, BLR);
  376.         break;
  377.         case TokPercent:
  378.         PushOp(&atomStack, &opStack, GenPercent, 130, BLR);
  379.         break;
  380.         case TokStar:
  381.         PushOp(&atomStack, &opStack, GenStar, 130, BLR);
  382.         break;
  383.         case TokMi:
  384.         PushOp(&atomStack, &opStack, GenMi, 120, BLR);
  385.         opStack->ex_Token = TokMi;
  386.         break;
  387.         case TokPl:
  388.         PushOp(&atomStack, &opStack, GenPl, 120, BLR);
  389.         opStack->ex_Token = TokPl;
  390.         break;
  391.  
  392.         case TokAnd:
  393.         PushOp(&atomStack, &opStack, GenAnd, 80, BLR);
  394.         break;
  395.         case TokOr:
  396.         PushOp(&atomStack, &opStack, GenOr, 60, BLR);
  397.         break;
  398.         case TokCarat:
  399.         PushOp(&atomStack, &opStack, GenXor, 70, BLR);
  400.         break;
  401.         case TokLtLt:
  402.         PushOp(&atomStack, &opStack, GenLShf, 110, BLR);
  403.         break;
  404.         case TokGtGt:
  405.         PushOp(&atomStack, &opStack, GenRShf, 110, BLR);
  406.         break;
  407.  
  408.         case TokQuestion:
  409.         PushOp(&atomStack, &opStack, GenQuestion, 30, BRL);
  410.         opStack->ex_Token = TokQuestion;
  411.         opStack->ex_Precedence = 0;
  412.         ++quests;
  413.         break;
  414.  
  415.         case TokColon:
  416.         if (quests == 0) {
  417.             notdone = 0;
  418.             break;
  419.         }
  420.         --quests;
  421.         /*
  422.          *  Combine opstack until the op is GenQuestion.  After
  423.          *  all is said and done the tree looks like:        :
  424.          *                           / \
  425.          *            a ? b : c          ?   c
  426.          *                         a b
  427.          */
  428.         while (opStack && opStack->ex_Token != TokQuestion)
  429.             CombineOp(&atomStack, &opStack);
  430.         if (opStack == NULL)
  431.             zerror(EFATAL, EFATAL_SYNTAX_ERROR_EXP);
  432.         CombineOp(&atomStack, &opStack);    /*    atom for a ? b    */
  433.         PushOp(&atomStack, &opStack, GenColon, 30, BRL);
  434.         break;
  435.  
  436.         /*
  437.          *    postfix operators, we stay in binary mode
  438.          */
  439.  
  440.         case TokLParen:
  441.         /*
  442.          *  Subroutine call.
  443.          */
  444.  
  445.         unary = 0;
  446.         t = GetToken();
  447.         {
  448.             Exp *exp = NULL;
  449.             Exp **pe = &exp;
  450.  
  451.             while (t && t != TokRParen) {
  452.             Exp *e;
  453.  
  454.             t = CompExp(t, pe, 0);
  455.             e = *pe;
  456.             pe = &e->ex_Next;
  457.             if (t != TokComma && t != TokRParen) {
  458.                 zerror(EFATAL_EXPECTED_COMMACLOSE);
  459.                 break;
  460.             }
  461.             if (t == TokComma)
  462.                 t = GetToken();
  463.             }
  464.             PushOp(&atomStack, &opStack, GenCall, 150, LR);
  465.             opStack->ex_ExpR = exp;
  466.             opStack->ex_Token= TokCall;
  467.         }
  468.         break;
  469.         case TokRParen:
  470.         unary = 0;
  471.         if (parens == 0) {
  472.             notdone = 0;
  473.             break;
  474.         }
  475.         --parens;
  476.         /*
  477.          *  Combine until we find the GenParen
  478.          */
  479.         while (opStack && opStack->ex_Token != TokLParen)
  480.             CombineOp(&atomStack, &opStack);
  481.         if (opStack == NULL)
  482.             zerror(EFATAL_SYNTAX_ERROR_EXP);
  483.         CombineOp(&atomStack, &opStack);    /*  now have atom for (exp) */
  484.         break;
  485.         case TokComma:
  486.         unary = 1;
  487.         if (parens == 0 && commaok == 0) {
  488.             notdone = 0;
  489.             break;
  490.         }
  491.         PushOp(&atomStack, &opStack, GenComma, 10, BLR);
  492.         break;
  493.         case TokPlPl:   /*    exp++    */
  494.         unary = 0;
  495.         PushOp(&atomStack, &opStack, GenPosInc, 150, LR);
  496.         opStack->ex_Token = TokPosInc;
  497.         break;
  498.         case TokMiMi:
  499.         unary = 0;
  500.         PushOp(&atomStack, &opStack, GenPosDec, 150, LR);
  501.         opStack->ex_Token = TokPosDec;
  502.         break;
  503.         case TokStrInd:
  504.         case TokStrElm:
  505.         unary = 0;
  506.         {
  507.             void (*func)(Exp **) = ((t == TokStrInd) ? GenStructInd : GenStructElm);
  508.  
  509.             PushOp(&atomStack, &opStack, GenStructInd, 150, LR);
  510.             t = GetToken();
  511.             if (t != TokId && /* t != TokLabelId && */ t != TokVarId && t != TokTypeId && t != TokEnumConst)
  512.             zerror(EFATAL_EXPECTED_STRUCT_TAG);
  513.             opStack->ex_Func = func;
  514.             opStack->ex_Symbol = LexSym;
  515.         }
  516.         break;
  517.         case TokLBracket:
  518.         unary = 0;
  519.         {
  520.             Exp *exp;
  521.  
  522.             t = CompExp(GetToken(), &exp, 1);
  523.             if (t != TokRBracket)
  524.             zerror(EERROR_EXPECTED_CLOSE_BRACKET);
  525.             PushOp(&atomStack, &opStack, GenArray, 150, LR);
  526.             opStack->ex_ExpR = exp;
  527.         }
  528.         break;
  529.         default:
  530.         notdone = 0;
  531.         break;
  532.         }
  533.     }
  534.     if (notdone) {
  535.         t = GetToken();
  536.         continue;
  537.     }
  538.     break;
  539.     }
  540.     while (opStack)
  541.     CombineOp(&atomStack, &opStack);
  542.     if (atomStack == NULL)
  543.     zerror(EFATAL_SYNTAX_ERROR_EXP);
  544.     if (parens)
  545.     zerror(EFATAL_EXPECTED_CLOSE_PARENS, parens);
  546.     if (atomStack->ex_Next)
  547.     zerror(EFATAL_SYNTAX_ERROR_EXP);
  548.     atomStack->ex_Next = NULL;
  549.     *pexp = atomStack;
  550.  
  551.     return(t);
  552. }
  553.  
  554. /*
  555.  *  precedence of 0 is for parenthesized expressions and never combines.
  556.  */
  557.  
  558. Local  void
  559. PushOp(patomStack, popStack, genFunc, precedence, order)
  560. Exp **patomStack;
  561. Exp **popStack;
  562. void (*genFunc)(Exp **);
  563. long precedence;
  564. long order;
  565.  
  566. {
  567.     Exp *exp;
  568.  
  569.     /*
  570.      *    If precedence then pop stack until get entry with lower precedence,
  571.      *    equal precedence breaks out only for left-to-right operations.
  572.      *    Parsing : in a ?: expression ignores precedence until ? is found
  573.      *    again.
  574.      */
  575.  
  576.     if (precedence) {
  577.     for (exp = *popStack; exp; exp = *popStack) {
  578.         if (precedence > exp->ex_Precedence)
  579.         break;
  580.         if (precedence == exp->ex_Precedence && (order & RL))
  581.         break;
  582.         CombineOp(patomStack, popStack);
  583.     }
  584.     }
  585.     exp = AllocTmpStructure(Exp);
  586.     exp->ex_Precedence = precedence;
  587.     exp->ex_Order = order;
  588.     exp->ex_Func = genFunc;
  589.     exp->ex_Next = *popStack;
  590.     exp->ex_LexIdx = LFBase->lf_Index;
  591.     *popStack = exp;
  592. }
  593.  
  594. Local  void
  595. PushAtom(patomStack, popStack, genFunc)
  596. Exp **patomStack;
  597. Exp **popStack;
  598. void (*genFunc)(Exp **);
  599. {
  600.     Exp *exp;
  601.  
  602.     if (HackTmpExp) {
  603.     exp = HackTmpExp;
  604.     setmem(exp, sizeof(Exp), 0);
  605.     HackTmpExp = NULL;
  606.     } else {
  607.     exp = AllocTmpStructure(Exp);
  608.     }
  609.  
  610.     exp->ex_Func = genFunc;
  611.     exp->ex_Next = *patomStack;
  612.     exp->ex_LexIdx = LFBase->lf_Index;
  613.     exp->ex_Flags= 0;
  614.     *patomStack = exp;
  615. }
  616.  
  617. Local  void
  618. CombineOp(patomStack, popStack)
  619. Exp **patomStack;
  620. Exp **popStack;
  621. {
  622.     Exp *exp = *popStack;    /*  get op  */
  623.     Exp *e1;
  624.     Exp *e2;
  625.  
  626.     if (exp == NULL)
  627.     zerror(EFATAL_SYNTAX_ERROR_EXP);
  628.     if ((e1 = *patomStack) == NULL)
  629.     zerror(EFATAL_SYNTAX_ERROR_EXP);
  630.  
  631.     if (exp->ex_Order & QBIN) {
  632.     e2 = e1->ex_Next;
  633.     if (e2 == NULL)
  634.         zerror(EFATAL_SYNTAX_ERROR_EXP);
  635.     *patomStack = e2->ex_Next;
  636.     exp->ex_ExpL = e2;
  637.     exp->ex_ExpR = e1;
  638.     exp->ex_Flags = 0;
  639.     /*exp->ex_Flags = (e1->ex_Flags | e2->ex_Flags) & EF_CALL;*/
  640.  
  641.     } else {
  642.     *patomStack = e1->ex_Next;
  643.     exp->ex_ExpL = e1;
  644.     exp->ex_Flags = 0;
  645.  
  646.     if (exp->ex_Token == TokCall && e1->ex_Token == TokVarRef) {
  647.         char prgno[16];
  648.         PragNode *pragma_call;
  649.  
  650.         if ((pragma_call = TestPragmaCall(e1->ex_Var, prgno)) != NULL) {
  651.         /*
  652.          *  Append base variable reference - A6 to end of
  653.          *  argument list.
  654.          */
  655.         Exp *ex = zalloc(sizeof(Exp));
  656.         Exp **pexp;
  657.         Symbol *sym = MakeSymbol(pragma_call->pn_Sym->Name, pragma_call->pn_Sym->Len, TokId, NULL);
  658.  
  659.         if (sym->LexId != TokVarId)
  660.             yerror(exp->ex_LexIdx, EFATAL_PRAGMA_BASE_UNDEF, sym->Len, sym->Name);
  661.  
  662.         for (pexp = &exp->ex_ExpR; (e1 = *pexp) != NULL; pexp = &e1->ex_Next)
  663.             ;
  664.         ex->ex_Func = GenVarRef;
  665.         ex->ex_Token = TokVarRef;
  666.         ex->ex_Symbol = sym;
  667.         ex->ex_Var = sym->Data;
  668.         ex->ex_Flags |= EF_SPECIAL;
  669.         ++ex->ex_Var->Refs;
  670.         *pexp = ex;
  671.         }
  672.     }
  673.     }
  674.     *popStack = exp->ex_Next;
  675.     exp->ex_Next = *patomStack;
  676.     *patomStack = exp;
  677. }
  678.  
  679. /*
  680.  *  Parse a braced expression.    An open brace refers to an explcit
  681.  *  downlevel while an expression may cause zero or more implicit
  682.  *  downlevel's.
  683.  *
  684.  *  exp->ex_Token is set to TokExpAssBlock for downlevel exp's
  685.  *  exp->ex_ExpL is the base of a list of expressions linked via ex_Next
  686.  */
  687.  
  688. short
  689. CompBracedAssign(short t, Type *type, Exp **pexp, short lbraced, Symbol *sym)
  690. {
  691.     Exp *exp;
  692.     long **caBase;
  693.     long index = 0;
  694.  
  695.     /*
  696.      *    create downlevel
  697.      */
  698.  
  699.     *pexp = exp = AllocTmpStructure(Exp);
  700.     pexp = &exp->ex_ExpL;
  701.     exp->ex_Type = type;
  702.     exp->ex_Token = TokExpAssBlock;
  703.     exp->ex_LexIdx = LFBase->lf_Index;
  704.     exp->ex_Func  = GenBracedAssign;
  705.     caBase = &exp->ex_ConstAry;
  706.  
  707.     for (;;) {
  708.     Type *subType;
  709.     int wantcomma = 0;
  710.  
  711.     if (type->Id == TID_STRUCT) {
  712.         if (index >= type->Args)        /* break condition */
  713.         break;
  714.         subType = type->Vars[index]->Type;    /* sub type       */
  715.         if (index) 
  716.         wantcomma = 1;
  717.     } else if (type->Id == TID_UNION) {
  718.         if (index)
  719.         break;
  720.         subType = type->Vars[0]->Type;
  721.     } else if (type->Id == TID_ARY) {
  722.         subType = type->SubType;
  723.         if (type->Size && index >= type->Size / subType->Size)
  724.         break;
  725.         if (index) 
  726.         wantcomma = 1;
  727.     } else {
  728.         subType = type;
  729.     }
  730.     if (subType->Id == TID_UNION || 
  731.         subType->Id == TID_STRUCT || 
  732.         subType->Id == TID_ARY
  733.     ) {
  734.         /*
  735.          *    level-down
  736.          */
  737.  
  738.         if (t == TokComma) {
  739.         if (wantcomma == 0)
  740.             zerror(EFATAL_SYNTAX_ERROR_EXP);
  741.         wantcomma = 0;
  742.         t = GetToken();
  743.         }
  744.  
  745.         if (t == TokRBrace)
  746.         break;
  747.  
  748.             if (wantcomma) {
  749.         zerror(EWARN_MISSING_COMMA);
  750.             }
  751.  
  752.         if (t == TokLBrace) {
  753.         t = CompBracedAssign(GetToken(), subType, pexp, 1, NULL);
  754.         if (t != TokRBrace)
  755.         {
  756.             zerror(EERROR_TOO_MANY_INITIALIZERS);
  757.             t = match_nesting(t);
  758.         }
  759.         t = GetToken();
  760.         } else {
  761.         t = CompBracedAssign(t, subType, pexp, 0, NULL);
  762.         }
  763.         ++index;
  764.         pexp = &(*pexp)->ex_Next;
  765.         if (t == TokRBrace || t == TokSemi)
  766.         break;
  767.     } else {
  768.         /*
  769.          *    terminal case for subType
  770.          *
  771.          *    A right-brace here may terminate the sequence, possible
  772.          *    unto multiple levels.
  773.          */
  774.  
  775.         if (t == TokComma) {
  776.         wantcomma = 0;
  777.         t = GetToken();
  778.         }
  779.  
  780.         if (t == TokRBrace || t == TokSemi)
  781.         break;
  782.  
  783.             if (wantcomma) {
  784.         zerror(EWARN_MISSING_COMMA);
  785.             }
  786.  
  787.         if (t == TokStrConst && type->Id == TID_ARY && subType->Size == 1) {
  788.         Exp *sexp;
  789.  
  790.         t = CompExp(t, pexp, 0);
  791.         sexp = *pexp;
  792.         Assert(sexp->ex_Token == TokStrConst);
  793.         index += sexp->ex_StrLen;
  794.  
  795.         /*
  796.          *  quietly delete the terminating \0 if string
  797.          *  overruns array.
  798.          */
  799.  
  800.         if (type->Size) {
  801.             if (index > type->Size) {
  802.             if (index - 1 == type->Size) {
  803.                 --index;
  804.                 --sexp->ex_StrLen;
  805.             } else {
  806.                 sexp->ex_StrLen -= (index - type->Size);
  807.                 index = type->Size;
  808.                 zerror(EERROR_ARRAY_CANNOT_HOLD_STRING);
  809.             }
  810.             } else if (index < type->Size && lbraced == 0) {
  811.             /*
  812.              *  If no { } was used to explicitly specify
  813.               *  initializers for this array, the string will
  814.              *  force the array to be terminated & zero filled
  815.              */
  816.  
  817.             long newLen = type->Size - index + sexp->ex_StrLen;
  818.             char *new = talloc(newLen);
  819.             movmem(sexp->ex_StrConst, new, sexp->ex_StrLen);
  820.  
  821.             sexp->ex_StrConst = new;
  822.             sexp->ex_StrLen = newLen;
  823.             index = type->Size;
  824.             }
  825.         }
  826.         pexp = &(*pexp)->ex_Next;
  827.         break;
  828.         } else {
  829.         /*
  830.          *  This is the nominal core, and where all the memory is
  831.          *  eaten up for statically initialized arrays.  Simple
  832.          *  integer constants are optimized (so we do not allocate
  833.          *  an entire Exp structure for each constant).
  834.          */
  835.  
  836.         t = CompExp(t, pexp, 0);
  837.         if (pexp == &exp->ex_ExpL && (*pexp)->ex_Token == TokIntConst) {
  838.             long *captr = talloc(sizeof(long) * 2);
  839.             Exp  *caexp = *pexp;
  840.  
  841.             *caBase = captr;
  842.             captr[1] = caexp->ex_Stor.st_IntConst;
  843.  
  844.             caBase = (long **)&captr[0];
  845.             HackTmpExp = caexp;
  846.             *pexp = NULL;
  847.         } else {
  848.             pexp = &(*pexp)->ex_Next;
  849.         }
  850.         ++index;
  851.         }
  852.  
  853.     }
  854.     if (subType == type) break;
  855.     }
  856.     *pexp = NULL;
  857.     *caBase = NULL;
  858.     HackTmpExp = NULL;        /*    don't leave stale cache */
  859.  
  860.     if (type->Id == TID_ARY && lbraced)
  861.     {
  862.        if (t == TokComma)
  863.           t = GetToken();
  864.     }
  865.     if (type->Size == 0)
  866.     {
  867.     if (type->Id == TID_ARY)
  868.         type->Size = index * type->SubType->Size;
  869.     else if (type->Id == TID_UNION || type->Id == TID_STRUCT)
  870.     {
  871.         Undefined_Tag(type, sym, exp->ex_LexIdx);
  872.         t = match_nesting(t);
  873.     }
  874.     }
  875.     return(t);
  876. }
  877.  
  878. short match_nesting(short t)
  879. {
  880.     int nesting = 1;
  881.     /* We now want to eat up all of the outstanding tokens to avoid a */
  882.     /* cascade of errors.                                             */
  883.     while(nesting)
  884.     {
  885.     if (t == TokRBrace) nesting--;
  886.     else if (t == TokLBrace) nesting++;
  887.     else if (t == 0) break;
  888.     if (nesting) t = GetToken();
  889.     }
  890.     return(t);
  891. }
  892.